#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import glob
from typing import List
from configmanager import ConfigManager
from transportprogress import batch_copy_multiple_paths, print_summary
from mylogger import log_info_file, log_info_console, log_error_console, log_warning_console
from help import show_help

def expand_wildcards(paths: List[str]) -> List[str]:
    """
    展开包含通配符的路径列表
    
    参数:
        paths: 可能包含通配符的路径列表
        
    返回:
        List[str]: 展开后的路径列表
    """
    expanded_paths = []
    for path in paths:
        try:
            # 尝试展开通配符
            expanded = glob.glob(path)
            if expanded:
                expanded_paths.extend(expanded)
            else:
                # 如果通配符没有匹配到任何文件，保留原始路径
                log_warning_console(f"没有找到匹配 '{path}' 的文件，将保留原始路径")
                expanded_paths.append(path)
        except Exception as e:
            log_warning_console(f"处理路径 '{path}' 时出错: {str(e)}, 将保留原始路径")
            expanded_paths.append(path)
    return expanded_paths

def parse_args() -> tuple:
    """
    解析命令行参数
    
    返回:
        tuple: (本地路径列表, 远程路径, 配置文件路径, 线程数, debug_mode)
    """
    args = sys.argv[1:]
    
    # 检查是否显示帮助
    if '-h' in args or '--help' in args:
        show_help()
        sys.exit(0)
    
    # 初始化参数
    threads = 10  # 默认线程数
    config_file = 'config.yaml'  # 默认配置文件
    local_paths = []
    remote_path = ""
    debug_mode = False
    
    # 解析参数
    i = 0
    while i < len(args):
        arg = args[i]
        if arg == '-c' or arg == '--config':
            # 配置文件参数
            if i + 1 < len(args):
                config_file = args[i + 1]
                i += 2
            else:
                log_error_console("-c 参数缺少配置文件路径")
                return [], "", "", 0, False
        elif arg == '-s' or arg == '--source':
            # 源端路径参数
            if i + 1 < len(args):
                # 检查下一个参数是否是另一个选项
                next_arg = args[i + 1]
                if not next_arg.startswith('-'):
                    local_paths.append(next_arg)
                    i += 2
                else:
                    # 如果下一个参数是选项，则没有提供源路径
                    log_error_console("-s 参数缺少源端路径")
                    return [], "", "", 0, False
            else:
                log_error_console("-s 参数缺少源端路径")
                return [], "", "", 0, False
        elif arg == '-d' or arg == '--destination':
            # 目标端路径参数
            if i + 1 < len(args):
                # 检查下一个参数是否是另一个选项
                next_arg = args[i + 1]
                if not next_arg.startswith('-'):
                    remote_path = next_arg
                    i += 2
                else:
                    # 如果下一个参数是选项，则没有提供目标路径
                    log_error_console("-d 参数缺少目标端路径")
                    return [], "", "", 0, False
            else:
                log_error_console("-d 参数缺少目标端路径")
                return [], "", "", 0, False
        elif arg == '--threads':
            # 线程数参数
            if i + 1 < len(args):
                try:
                    threads = int(args[i + 1])
                    i += 2
                except ValueError:
                    log_error_console("--threads 参数格式错误，应为 --threads 数字")
                    return [], "", "", 0, False
            else:
                log_error_console("--threads 参数缺少线程数")
                return [], "", "", 0, False
        elif arg == '--debug':
            # 调试模式参数
            debug_mode = True
            i += 1
        else:
            # 非选项参数，尝试将其作为源路径（处理通配符展开的情况）
            local_paths.append(arg)
            i += 1
    
    # 检查必要参数
    if not local_paths:
        log_error_console("缺少源端路径，请使用 -s 参数指定")
        return [], "", "", 0, False
    
    if not remote_path:
        log_error_console("缺少目标端路径，请使用 -d 参数指定")
        return [], "", "", 0, False
    
    return local_paths, remote_path, config_file, threads, debug_mode

def validate_local_paths(local_paths: List[str]) -> bool:
    """
    验证所有本地路径是否有效
    
    参数:
        local_paths: 本地路径列表
        
    返回:
        bool: 所有路径都有效返回True，否则返回False
    """
    all_valid = True
    total_paths = len(local_paths)
    
    # 对于大量文件，我们先快速验证基本存在性，不进行详细日志记录
    if total_paths > 50:
        log_info_console(f"正在快速验证 {total_paths} 个路径，仅显示错误信息...")
        for path in local_paths:
            if not os.path.exists(path):
                log_error_console(f"本地路径不存在: {path}")
                all_valid = False
    else:
        # 少量文件时详细验证
        for path in local_paths:
            if not os.path.exists(path):
                log_error_console(f"本地路径不存在: {path}")
                all_valid = False
            elif not os.path.isfile(path) and not os.path.isdir(path):
                log_error_console(f"本地路径既不是文件也不是目录: {path}")
                all_valid = False
            else:
                log_info_file(f"验证通过的本地路径: {path}")
    
    return all_valid

def validate_thread_count(threads: int) -> bool:
    """
    验证线程数是否在有效范围内
    
    参数:
        threads: 线程数
        
    返回:
        bool: 线程数有效返回True，否则返回False
    """
    if not 1 <= threads <= 100:
        log_error_console(f"线程数必须在1到100之间，当前值: {threads}")
        return False
    return True

def main() -> int:
    """
    主函数，协调整个SCP批量传输过程
    
    返回:
        int: 程序退出码
    """
    
    try:
        # 解析命令行参数
        local_paths, remote_path, config_file, threads, debug_mode = parse_args()
        
        # 如果解析失败，直接返回错误
        if not local_paths or not remote_path:
            return 1
        
        # 验证线程数
        if not validate_thread_count(threads):
            return 1
        
        # 验证配置文件存在
        if not os.path.isfile(config_file):
            log_error_console(f"配置文件不存在: {config_file}")
            return 1
        
        # 根据调试模式调整日志记录
        if debug_mode:
            log_info_console(f"[调试模式] 使用配置文件: {config_file}")
            log_info_console(f"[调试模式] 线程数: {threads}")
        log_info_file(f"使用配置文件: {config_file}")
        log_info_file(f"线程数: {threads}")
        
        # 展开通配符
        expanded_paths = expand_wildcards(local_paths)
        log_info_file(f"展开后的本地路径: {', '.join(expanded_paths)}")
        if debug_mode:
            log_info_console(f"[调试模式] 展开后的本地路径: {', '.join(expanded_paths)}")
        
        # 验证本地路径
        if not validate_local_paths(expanded_paths):
            log_error_console("存在无效的本地路径，程序退出")
            return 1
        
        # 加载配置
        config_manager = ConfigManager(config_file)
        if not config_manager.load_config():
            log_error_console("加载配置文件失败，程序退出")
            return 1
        
        # 获取服务器配置
        server_configs = config_manager.get_server_configs()
        if not server_configs:
            log_error_console("没有可用的服务器配置，请检查配置文件")
            return 1
            
        log_info_file(f"将复制文件到 {len(server_configs)} 台服务器")
        log_info_file(f"远程目标路径: {remote_path}")
        if debug_mode:
            log_info_console(f"[调试模式] 将复制文件到 {len(server_configs)} 台服务器")
            log_info_console(f"[调试模式] 远程目标路径: {remote_path}")
        
        # 执行批量复制
        success_count, fail_count, total_size = batch_copy_multiple_paths(
            servers=server_configs,
            local_paths=expanded_paths,
            remote_path=remote_path,
            threads=threads,
            debug_mode=debug_mode
        )
        
        # 打印摘要
        print_summary(success_count, fail_count, total_size)
        
        # 根据结果返回退出码
        return 0 if fail_count == 0 else 1
        
    except KeyboardInterrupt:
        log_warning_console("\n程序被用户中断")
        return 130
    except Exception as e:
        log_error_console(f"发生未预期的错误: {str(e)}")
        return 1


if __name__ == "__main__":
    sys.exit(main())
